package service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import utils.LoggerUtil;

import java.io.*;
import java.util.concurrent.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Compress {
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    // 定义用于压缩文件的线程池
    private static final ExecutorService compressionExecutor = Executors.newFixedThreadPool(4);
    private static String BACKUP_DIR;
    private final static Logger LOGGER = LoggerFactory.getLogger(NormalStore.class);
    private final static String logFormat = "[BackUP][{}]: {}";
//    任务开始前的初始延迟时间
    private final static long initialDelay = 10;
//    任务执行的周期
    private final static long period = 10;

    public static void startScheduledCompression(String backupDir) {
        BACKUP_DIR = backupDir;
        Runnable compressTask = () -> {
            try {
                compressBackupFiles();
            } catch (Exception e) {
                e.printStackTrace();
            }
        };
        scheduler.scheduleAtFixedRate(compressTask, initialDelay, period, TimeUnit.MINUTES);
        LoggerUtil.info(LOGGER,logFormat,"Enable scheduled compressed backup files",initialDelay,period);
    }

    /**
     * 关闭调度器和压缩执行器
     *
     */
    public static void shutdown() {
        scheduler.shutdown();
        compressionExecutor.shutdown();
        try {
            if (!scheduler.awaitTermination(1, TimeUnit.MINUTES)) {
                scheduler.shutdownNow();
            }
            if (!compressionExecutor.awaitTermination(1, TimeUnit.MINUTES)) {
                compressionExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            compressionExecutor.shutdownNow();
        }
    }

    /**
     * 压缩备份文件
     * @throws IOException
     */
    private static void compressBackupFiles() throws IOException {
        LoggerUtil.info(LOGGER,logFormat,"Compressing backup files....");
        File dir = new File(BACKUP_DIR);
        // find
        File[] files = dir.listFiles((d, name) -> name.matches("data_\\d+\\.table"));
        // 将备份文件都压缩到压缩包里
        if (files != null && files.length > 0) {
            String zipFileName = "backup_" + System.currentTimeMillis() + ".zip";
            File zipFile = new File(dir, zipFileName);

            try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)))) {
                CountDownLatch latch = new CountDownLatch(files.length); // 用于等待所有文件处理完成
                for (File file : files) {
                    compressionExecutor.submit(() -> {
                        try {
                            compressFile(file, zos);
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            latch.countDown(); // 减少计数
                        }
                    });
                }
                latch.await(); // 等待所有文件处理完成
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
//            // 删除源备份文件
//            for (File file : files) {
//                file.delete();
//            }
        }
    }

    private static synchronized void compressFile(File file, ZipOutputStream zos) throws IOException {
        try (FileInputStream fis = new FileInputStream(file)) {
            zos.putNextEntry(new ZipEntry(file.getName()));
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, length);
            }
            zos.closeEntry();
            System.out.println("File added to zip: " + file.getName());
        }
    }


}
